
import { _decorator, Vec2, sys, Prefab, instantiate, find, Node, view, UITransform } from 'cc';
import { InputDefine } from './input_define';
import { Joystick } from './joystick';
import { Keyboard } from './keyboard';
import { MouseInput } from './mouse_input';
import { ResourceUtil } from '../../farmework/resource_util';
const { ccclass, property } = _decorator;

/**
 * 输入管理类
 */
@ccclass('InputManager')
export class InputManager {
    private static _instance: InputManager;

    public static get instance () {
        if (this._instance) {
            return this._instance;
        }

        this._instance = new InputManager();
        return this._instance;
    }

    public inputModel: InputDefine.InputMode = InputDefine.InputMode.Keyboard;

    public touchEnable: boolean = false;

    public primaryMovement: Vec2 = new Vec2; // 左方向盘
    public secondaryMovement: Vec2 = new Vec2;  // 右边方向盘

    public scroll: Vec2 = new Vec2;

    private _keyboard: Keyboard | null = null;
    private _mouseInput: MouseInput | null = null;
    private _inputKeys: Map<string, boolean> = new Map();

    private _joystickList: Joystick[] = [];


    /**
     * 绑定键盘按键
     * @param inputModel 
     */
    public bindKeyborard (inputModel = InputDefine.InputMode.Keyboard) {
        if (inputModel == InputDefine.InputMode.KeyboardAndMouse) {
            this._keyboard = new Keyboard(this.primaryMovement, null, this._inputKeys);
            this._mouseInput = new MouseInput(this.secondaryMovement, this.scroll, this._inputKeys);
        } else if (inputModel == InputDefine.InputMode.Keyboard) {
            this._keyboard = new Keyboard(this.primaryMovement, this.secondaryMovement, this._inputKeys);
        } else {
            this._keyboard = new Keyboard(null, null, this._inputKeys);
        }
    }

    /**
     * 绑定摇杆
     * @param joystick 
     * @param isPrimary 
     */
    public bindJoystick (joystick: Joystick, isPrimary: boolean = true) {
        if (isPrimary) {
            joystick.bindInput(this.primaryMovement);
        } else {
            joystick.bindInput(this.secondaryMovement);
        }
        this._joystickList.push(joystick)
    }

    /**
     * 取消绑定
     */
    public destory () {
        this._keyboard && this._keyboard.destory();
        this._keyboard = null;

        this._mouseInput && this._mouseInput.destory();
        this._mouseInput = null;

        this._joystickList.forEach((joystick) => {
            joystick.bindInput(null);
            joystick.node.removeAllChildren();
        });
        this._joystickList.length = 0;
    }

    /**
     * 重制输入操作
     */
    public async resetDefaultInput (inputModel = InputDefine.InputMode.Keyboard) {
        this.destory();
        if (inputModel == InputDefine.InputMode.Joystick || !sys.isBrowser) {
            this.inputModel = InputDefine.InputMode.Joystick;
            let prefba = await ResourceUtil.getUIPrefabRes(InputDefine.DefaultJoystickPath);
            let width = view.getVisibleSize().width;
            let left = instantiate(prefba) as Node;
            left.parent = find("Canvas");
            left.getComponent(UITransform)!.width = width / 2;
            left.setPosition(-width / 4, 0);

            let right = instantiate(prefba) as Node;
            right.parent = find("Canvas");
            right.getComponent(UITransform)!.width = width / 2;
            right.setPosition(width / 4, 0);

            this.bindJoystick(left.getComponent(Joystick)!);
            this.bindJoystick(right.getComponent(Joystick)!, false);
        }
        this.inputModel = inputModel;
        this.bindKeyborard(this.inputModel);
    }

    public getPrimaryMovement () {
        return this.primaryMovement;
    }

    public getSecondaryMovement () {
        return this.secondaryMovement;
    }

    /**
     * 设置主摇杆
     * @param x 
     * @param y 
     */
    public setPrimaryMovement (x: number, y: number) {
        this.primaryMovement.x = x;
        this.primaryMovement.y = y;
    }

    /**
     * 设置第二摇杆
     * @param movementX 
     * @param movementY 
     */
    public setSecondaryMovement (movementX: number, movementY: number) {
        this.secondaryMovement.x = movementX;
        this.secondaryMovement.y = movementY;
    }

    /**
     * 获取滚轮
     * @param scrollX 
     * @param scrollY 
     */
    public setScroll (scrollX: number, scrollY: number) {
        this.scroll.x = scrollX;
        this.scroll.y = scrollY;
    }

    /**
     * 获取按键按下
     * @param control 
     * @returns 
     */
    public getKeyDown (control: string) {
        if (this._inputKeys.has(control)) {
            return this._inputKeys.get(control);
        }
        return false;
    }
}
